package com.jfirer.validator.util;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import javax.validation.Constraint;
import javax.validation.ValidationException;
import javax.validation.groups.Default;

public class Commons
{
	public static Map<String, Object> getAttributes(Annotation annotation)
	{
		Map<String, Object> result = new HashMap<String, Object>();
		for (Method method : annotation.annotationType().getMethods())
		{
			boolean notAnnotationMethod = method.getParameterTypes().length != 0 || method.getReturnType() == Void.class || method.getReturnType() == void.class;
			if (notAnnotationMethod)
			{
				continue;
			}
			method.setAccessible(true);
			try
			{
				Object invoke = method.invoke(annotation);
				result.put(method.getName(), invoke);
			}
			catch (Exception e)
			{
				ValidationException exception = new ValidationException(e);
				throw exception;
			}
		}
		return result;
	}
	
	public static Set<?> arrayToSet(Object[] array)
	{
		Set<Object> set = new HashSet<Object>();
		for (Object each : array)
		{
			set.add(each);
		}
		return set;
	}
	
	public static boolean isConstraintAnnotation(Annotation annotation)
	{
		return annotation.annotationType().isAnnotationPresent(Constraint.class);
	}
	
	public static boolean isMutliValueConstraintAnnotation(Annotation annotation)
	{
		if (annotation.annotationType().getSimpleName().equals("List") == false)
		{
			return false;
		}
		try
		{
			Method method = annotation.annotationType().getMethod("value");
			if (method.getReturnType().isArray() == false || method.getReturnType().getComponentType().isAnnotation() == false || method.getReturnType().getComponentType().isAnnotationPresent(Constraint.class) == false)
			{
				return false;
			}
			return true;
		}
		catch (Exception e)
		{
			return false;
		}
	}
	
	public static Annotation[] getMutliValueConstraintAnnotation(Annotation annotation)
	{
		try
		{
			Method method = annotation.annotationType().getMethod("value");
			method.setAccessible(true);
			Annotation[] result = (Annotation[]) method.invoke(annotation);
			return result;
		}
		catch (Exception e)
		{
			throw new ValidationException(e);
		}
	}
	
	@SuppressWarnings("unchecked")
	public static Set<Class<?>> defineValidateGroups(Class<?>... groups)
	{
		groups = groups.length == 0 ? new Class<?>[] { Default.class } : groups;
		return (Set<Class<?>>) arrayToSet(groups);
	}
	
	public static final boolean intersection(Collection<Class<?>> groups, Class<?>... validateGroups)
	{
		for (Class<?> each : validateGroups)
		{
			if (groups.contains(each))
			{
				return true;
			}
		}
		return false;
	}
	
	public static final boolean intersection(Set<Class<?>> groups, Set<Class<?>> validateGroups)
	{
		return Collections.disjoint(groups, validateGroups) == false;
	}
	
	/**
	 * 获取该类的所有field对象，如果子类重写了父类的field，则只包含子类的field
	 * 
	 * @param entityClass
	 * @return
	 */
	public static Field[] getAllFields(Class<?> entityClass)
	{
		Set<Field> set = new TreeSet<Field>(new Comparator<Field>() {
			// 只需要去重，并且希望父类的field在返回数组中排在后面，所以比较全部返回1
			@Override
			public int compare(Field o1, Field o2)
			{
				if (o1.getName().equals(o2.getName()))
				{
					return 0;
				}
				else
				{
					return 1;
				}
			}
		});
		while (entityClass != Object.class && entityClass != null)
		{
			for (Field each : entityClass.getDeclaredFields())
			{
				set.add(each);
			}
			entityClass = entityClass.getSuperclass();
		}
		return set.toArray(new Field[set.size()]);
	}
}
